#include "app_cfg.h"
#include "bsp.h"

#define S3C2440_TIMER_TCON      0x51000008
#define S3C2440_TIMER_TCNTB4    0x5100003c
#define S3C2440_SRCPND          0x4a000000
#define S3C2440_INTMOD          0x4a000004
#define S3C2440_INTMSK          0x4a000008
#define S3C2440_INTPND          0x4a000010

#define TIMER4_INTERVAL         1024

#define __raw_readl(a) *(volatile unsigned int *)(a)
#define __raw_writel(v,a) *(volatile unsigned int *)(a) = (v)

extern void OS_CPU_InitExceptVect(void);
extern void OS_CPU_SR_IRQ_En(void);

void gpio_leds_init(void)
{
    unsigned int con;

    con = __raw_readl(S3C2440_GPBCON);
    con |= (S3C2440_GPB5_OUTP | S3C2440_GPB6_OUTP | S3C2440_GPB7_OUTP |
            S3C2440_GPB8_OUTP);
    __raw_writel(con, S3C2440_GPBCON);

    __raw_writel(0xff, S3C2440_GPBUP);
}

void LED_On(INT8U n)
{
    unsigned int dat;

    /* turn off all other led, leave on only one */
    if (n < 1 || n > 4)
        return;

    APP_TRACE_DEBUG(("Turn on %d led, other off.\n", n));

    dat = __raw_readl(S3C2440_GPBDAT);
    dat |= 0xff;

    dat &= ~(1<<(n + 4));

    __raw_writel(dat, S3C2440_GPBDAT);
}

void outbyte(char c)
{
    WrUTXH0(c);
}

void BSP_ClearIntPending(void)
{
    INT32U intpnd;
    INT32U srcpnd;
    intpnd = __raw_readl(S3C2440_INTPND);
    srcpnd = __raw_readl(S3C2440_SRCPND);

    __raw_writel(srcpnd, S3C2440_SRCPND);
    __raw_writel(intpnd, S3C2440_INTPND);
}

INT32U BSP_IsTimer4Pending(void)
{
    INT32U intpnd;
    intpnd = __raw_readl(S3C2440_INTPND);
    return (intpnd & (1 << 14));
}

void BSP_InstallTimer4(void)
{
    INT32U tcon;
    INT32U intmsk;
    INT32U intmod;

    tcon = __raw_readl(S3C2440_TIMER_TCON);
    tcon |= 0x100000;
    __raw_writel(tcon, S3C2440_TIMER_TCON);

    __raw_writel(TIMER4_INTERVAL, S3C2440_TIMER_TCNTB4);

    /* Enable Timer4 IRQ */
    intmod = __raw_readl(S3C2440_INTMOD);
    intmod &= ~(1<<14);
    __raw_writel(intmod, S3C2440_INTMOD);

    /* Timer4 interrupt mask */
    intmsk = __raw_readl(S3C2440_INTMSK);
    intmsk &= ~(1<<14);
    __raw_writel(intmsk, S3C2440_INTMSK);
}

void BSP_Init(void)
{
    OS_CPU_InitExceptVect();
    OS_CPU_SR_IRQ_En();
    gpio_leds_init();
}

void CPU_Init(void)
{
}
